Skip to content

test(app-showcase): B3 cascading-select fixture — server-enforced dynamic options (#2559)#3006

Merged
os-zhuang merged 1 commit into
mainfrom
claude/b3-server-option-enforcement-a004hl
Jul 16, 2026
Merged

test(app-showcase): B3 cascading-select fixture — server-enforced dynamic options (#2559)#3006
os-zhuang merged 1 commit into
mainfrom
claude/b3-server-option-enforcement-a004hl

Conversation

@os-zhuang

@os-zhuang os-zhuang commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Context

The remaining framework half of B3 (dynamic field options / cascading selects — objectui#1583). The objectui client (per-option visibleWhen + dependsOn, #2284 / #2215) and the build-time guardrail + ADR-0058 + browser e2e (objectui#2547) already shipped. This PR delivers the served showcase fixture that exercises the server-side enforcement, per objectui#2559 item 2.

The server-side option-value enforcement itself already landed on main in #2915@objectstack/objectql evaluateOptionVisibility in the rule-validator, wired into engine.createData/update with buildEvalUser, and unit-tested in rule-validator.option-visibility.test.ts. This PR does not re-implement it; it adds the fixture that demonstrates and end-to-end-verifies it.

What's added

A new showcase object showcase_cascade (examples/app-showcase/src/data/objects/cascading-select.object.ts), registered in objects/index.ts and wired into the Showcase app's Data Model nav:

  • countryprovince cascadeprovince declares dependsOn: ['country'] and each option gates itself with a per-option visibleWhen CEL predicate (record.country == 'cn' …). The client narrows the offered set; the objectql rule-validator re-evaluates the submitted value and rejects an out-of-set one ({ field, code: 'invalid_option' }).
  • role-gated tier.restrictedvisibleWhen: "'admin' in current_user.positions", enforced server-side the same way.

public_read_write so the seeded admin (and the live e2e) can create against it without a bespoke permission set; belonging to no permission set, it stays out of the ADR-0090 access-matrix.json snapshot. Predicates use the P (CEL) tag — same authoring shape as showcase_invoice's field-level visibleWhen.

Verification

  • pnpm --filter @objectstack/example-showcase test55/55 green (coverage, seed, gap-fill, …); tsc --noEmit clean.
  • @objectstack/objectql rule-validator.option-visibility.test.ts15/15 (the server verdict).
  • Live against a fresh backend (objectstack dev --seed-admin --fresh):
    • POST /api/v1/data/showcase_cascade {country:'us',province:'zj'}400 VALIDATION_FAILED / invalid_option.
    • {country:'cn',province:'zj'}201.
    • {tier:'restricted'} (seeded admin, no admin position) → 400 invalid_option — role gating works.
    • GET /api/v1/meta/object/showcase_cascade serves the per-option visibleWhen to the client.

Related

🤖 Generated with Claude Code

https://claude.ai/code/session_01S91NyYJURiQTKmF9q3AXxg

…hen + role-gated option (#2559)

Adds `showcase_cascade`, a served fixture that exercises the B3 server-side
option-value enforcement (objectql `evaluateOptionVisibility`, #2915 / #1583):

- country → province cascade — `province` declares `dependsOn: ['country']`
  and each option gates itself with a `visibleWhen` CEL predicate. The client
  narrows the offered set; the rule-validator rejects an out-of-set submit
  (`{ field, code: 'invalid_option' }`).
- a role-gated `tier.restricted` option (`'admin' in current_user.positions`),
  enforced server-side the same way.

`public_read_write` (no permission set → absent from the ADR-0090 access-matrix),
wired into the Showcase app's Data Model nav. Verified live against a fresh
backend: POST /api/v1/data/showcase_cascade rejects country=us+province=zj
(400 invalid_option) and accepts country=cn+province=zj (201);
GET /api/v1/meta/object/showcase_cascade serves the per-option visibleWhen to the
client. Drives objectui e2e/live/cascading-options.spec.ts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S91NyYJURiQTKmF9q3AXxg
@vercel

vercel Bot commented Jul 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jul 16, 2026 4:11am

Request Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants